<?php

namespace App\Service\Cruise\CruiseTour;

use App\Enums\BaseErrorCode;
use App\Exceptions\Custom\ResponseHttpException;
use App\Library\Rms\RmsShopApi;
use App\Models\Common\ResourcesModel;
use App\Models\Cruise\CruiseCheckDetailModel;
use App\Models\Cruise\CruiseCheckRectifyModel;
use App\Models\Cruise\CruiseCheckTaskModel;
use App\Models\Cruise\CruiseOrderModel;
use App\Models\Cruise\CruiseOrderProcessModel;
use App\Models\Cruise\CruiseTaskOrderMappingModel;
use App\Models\Cruise\CruiseTemplateModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Service\Cruise\Check\CruiseCheckRectifyService;
use App\Service\Cruise\Mission\CruiseTourInputService;
use App\Service\OpenShop\User\RmsUserService;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Kuafu\Snow\KfSnow;

class CruiseTourService
{

    /**
     * 巡检记录列表
     * @param int $shopId
     * @param int $pageSize
     * @param int $pageNum
     * @param int $sysTemplateType
     * @return array
     */
    public static function getList(int $shopId, int $pageSize, int $pageNum, int $sysTemplateType = CruiseTemplateModel::SYS_TEMPLATE_TOUR): array
    {
        $cruiseOrderIds = CruiseOrderModel::query()
            ->where('type', CruiseTemplateModel::TYPE_6)
            ->orderByDesc('updatedAt')
            ->when(
                $shopId, function ($query) use ($shopId) {
                $query->where("shopId", $shopId);
            }
            )
            ->pluck('id')
            ->toArray();

        $cruiseCheckDetail = CruiseCheckDetailModel::query()
            ->orderByDesc('createdAt')
            ->whereIn('orderId', $cruiseOrderIds)
            ->whereIn('reportResult', [CruiseCheckDetailModel::REPORT_RESULT_QUALIFIED, CruiseCheckDetailModel::REPORT_RESULT_UNQUALIFIED, CruiseCheckDetailModel::REPORT_RESULT_CANCEL])
            ->with(['cruiseOrderRel']);


        $paginator = $cruiseCheckDetail
            ->where('sysTemplate', $sysTemplateType)
            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $shopList = array_column((new RmsShopApi())->getShopByIds([$shopId], ['id', 'shopCode', 'name'])['data']['shopList'] ?? [], null, 'id');
        $list     = $paginator->map(
            function (CruiseCheckDetailModel $checkDetailModel) use ($shopList, $sysTemplateType) {
                return [
                    'id'         => $checkDetailModel->id,
                    'shopInfo'   => $shopList[$checkDetailModel->cruiseOrderRel->shopId]['shopCode'] . ' ' . $shopList[$checkDetailModel->cruiseOrderRel->shopId]['name'],
                    'code'       => $checkDetailModel->code,
                    'statusText' => CruiseCheckDetailModel::REPORT_RESULT_MAPPING[$checkDetailModel->reportResult] ?? '-',
                    'status'     => $checkDetailModel->reportResult,
                    'totalNum'   => $checkDetailModel->totalNum,
                    'failNum'    => $checkDetailModel->failNum,
                    'createdAt'  => $checkDetailModel->createdAt->toDateTimeString(),
                    'dealUid'    => $checkDetailModel->dealUid,
                    'handler'    => $checkDetailModel->dealName,
                    'taskName'   => $checkDetailModel->cruiseOrderRel->getTaskName($checkDetailModel->taskId),
                ];
            }
        );

        return [
            'list'           => $list,
            'count'          => $paginator->total(),
            'pageNum'        => $pageNum,
            'pageSize'       => $pageSize,
        ];
    }

    /**
     * 巡检记录详情
     * @param int $id
     * @return array
     */
    public static function info(int $id): array
    {
        $cruiseCheckDetailQuery = CruiseCheckDetailModel::query()->find($id);
        if (null == $cruiseCheckDetailQuery) {
            return [];
        }
        return [
            'statusText'   => CruiseCheckDetailModel::REPORT_RESULT_MAPPING[$cruiseCheckDetailQuery->reportResult] ?? '-',
            'status'       => $cruiseCheckDetailQuery->reportResult,
            'totalNum'     => $cruiseCheckDetailQuery->totalNum,
            'code'         => $cruiseCheckDetailQuery->code,
            'failNum'      => $cruiseCheckDetailQuery->failNum,
            'createdAt'    => $cruiseCheckDetailQuery->createdAt->toDateString(),
            'totalScore'   => $cruiseCheckDetailQuery->totalScore,
            'successScore' => $cruiseCheckDetailQuery->successScore,
            'actualScore'  => $cruiseCheckDetailQuery->actualScore,
            'inputs'       => [
                'lists'    => (new CruiseCheckRectifyService(0, 0))->reportsLists($cruiseCheckDetailQuery->id, CruiseCheckRectifyModel::STATUS_WAIT_TOTAL, false),
                'classify' => (new CruiseCheckRectifyService(0, 0))->reportsListsGroupByRectifyStatus($cruiseCheckDetailQuery->id),
            ]
        ];
    }


    /**
     * 生成订单
     * @param int $shopId
     * @param int $userId
     * @param bool $isInitOrder
     * @return CruiseOrderModel|Builder|Model|object
     */
    public static function getOrder(int $shopId, int $userId, $isInitOrder = false)
    {
        $cruiseOrderModel = CruiseOrderModel::query()
            ->where('shopId', $shopId)
            ->where('handlerId', $userId)
            ->where('type', CruiseOrderModel::TYPE_CHECK_TOUR)
            ->whereIn('status', [CruiseOrderModel::STATUS_NOT_SUBMIT, CruiseOrderModel::STATUS_NOT_MODIFY])
            ->orderByDesc('id')
            ->first();
        if (!$cruiseOrderModel && $isInitOrder) {
            return self::initOrder($shopId, $userId);
        }
        if (!$cruiseOrderModel) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "不存在的云巡店任务 店铺id:{$shopId}");
        }
        return $cruiseOrderModel;
    }

    /**
     * 生成订单
     * @param int $shopId
     * @param int $userId
     * @return CruiseOrderModel
     */
    public static function initOrder(int $shopId, int $userId): CruiseOrderModel
    {
        DB::beginTransaction();
        try {
            $templateId = CruiseTemplateModel::getTemplateIdBySysTemplate(CruiseTemplateModel::SYS_TEMPLATE_TOUR);
            $template   = CruiseTemplateModel::query()->find($templateId);

            //添加任务表
            $taskName        = $template->name;
            $cruiseCheckTask = CruiseCheckTaskModel::add($taskName, $templateId);

            //添加订单表
            $cruiseOrder             = new CruiseOrderModel();
            $cruiseOrder->orderNo    = (string)OpenShopMainProcessModel::query()->where('shopId', $shopId)->value('orderNo');
            $cruiseOrder->shopId     = $shopId;
            $cruiseOrder->type       = CruiseTemplateModel::TYPE_6;
            $cruiseOrder->status     = CruiseOrderModel::STATUS_NOT_SUBMIT;
            $cruiseOrder->handlerId  = $userId;
            $cruiseOrder->templateId = $templateId;
            $cruiseOrder->save();

            //添加日志表
            CruiseOrderProcessModel::initCruiseOrderProcess($cruiseOrder->id);

            //添加关联关系
            CruiseTaskOrderMappingModel::add($cruiseCheckTask->id, $cruiseOrder->id);

            //生成巡检报告
            $cruiseCheckDetail               = new CruiseCheckDetailModel();
            $cruiseCheckDetail->code         = KfSnow::nextIdCache();
            $cruiseCheckDetail->orderId      = $cruiseOrder->id;
            $cruiseCheckDetail->taskId       = $cruiseCheckTask->id;
            $cruiseCheckDetail->systemplate  = CruiseTemplateModel::SYS_TEMPLATE_TOUR;
            $cruiseCheckDetail->templateType = CruiseTemplateModel::TYPE_6;
            $cruiseCheckDetail->checkType    = CruiseCheckDetailModel::CHECK_TYPE_COMMON;
            $cruiseCheckDetail->reportResult = CruiseCheckDetailModel::REPORT_RESULT_INIT;
            $cruiseCheckDetail->veto         = CruiseCheckDetailModel::VETO_ON;
            $cruiseCheckDetail->templateId   = $templateId;
            $cruiseCheckDetail->taskName     = $taskName;

            if ($userId) {
                $cruiseCheckDetail->dealUid  = $userId;
                $cruiseCheckDetail->dealName = RmsUserService::getRmsUserInfoByUserIds([$userId], [], true)['data'][0]['username'] ?? '';
            }
            $cruiseCheckDetail->save();

            // 生成input
            (new CruiseTourInputService($cruiseOrder->id, $shopId, $userId))->initOrderInput(false, $templateId);
            DB::commit();
        } catch (\Exception $exception) {
            Log::warning($exception);
            DB::rollBack();
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "创建任务失败");
        }
        return $cruiseOrder;
    }

    /**
     * 截图、视频资源上传
     * @param array $files
     * @param int $shopId
     * @param int $userId
     * @param int $deviceId
     */
    public function uploadResources(array $files, int $shopId, int $userId, int $deviceId): void
    {
        // resource insert
        foreach ($files as $file) {
            ResourcesModel::moduleBusinessResourcesBuild(
                ResourcesModel::MODULE_TYPE_TOUR,
                ResourcesModel::BUSINESS_OPEN_TOUR,
                $file['type'],
                $shopId,
                ltrim(parse_url($file['url'], PHP_URL_PATH), '/'),
                ResourcesModel::IS_PUBLIC_YES,
                json_encode(['type' => $file['type'], 'name' => $file['name'] ?? "", 'thumbnail' => $file['thumbnail'] ?? "", 'deviceId' => $deviceId]),
                $userId
            );
        }
        ResourcesModel::moduleBusinessResourcesSave();
    }

    /**
     * 截图、视频资源库列表
     * @param int $shopId
     * @param string $type
     * @param int $deviceId
     * @param string $startTime
     * @param string $endTime
     * @param int $pageSize
     * @param int $pageNum
     * @return array
     */
    public function resourcesList(int $shopId, string $type, int $deviceId, string $startTime, string $endTime, int $pageSize, int $pageNum): array
    {
        $paginator = ResourcesModel::query()
            ->where('module', ResourcesModel::MODULE_TYPE_TOUR)
            ->where('business', ResourcesModel::BUSINESS_OPEN_TOUR)
            ->where('businessId', $shopId)
            ->when(
                $type, function ($query) use ($type) {
                $query->where('name', $type);
            }
            )
            ->when(
                $startTime && $endTime, function ($query) use ($startTime, $endTime) {
                $query->whereBetween('createdAt', [strtotime($startTime), strtotime($endTime) + 86399]);
            }
            )
            ->when(
                $deviceId, function ($query) use ($deviceId) {
                $query->whereRaw(DB::raw("JSON_CONTAINS(extra, JSON_OBJECT('deviceId', {$deviceId}))"));
            }
            )
            ->orderByDesc('id')
            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        $lists = $paginator->map(
            function ($resourcesModel) {
                $extra = json_decode($resourcesModel->extra, true);
                return [
                    'id'        => $resourcesModel->id,
                    'url'       => picturePath($resourcesModel->url),
                    'type'      => $extra['type'] ?? "",
                    'name'      => $extra['name'] ?? "",
                    'thumbnail' => $extra['thumbnail'] ?? "",
                ];
            }
        );

        return [
            'pageNum'   => $paginator->currentPage(),
            'pageSize'  => $paginator->perPage(),
            'pageCount' => ceil($paginator->total() / $paginator->perPage()),
            'count'     => $paginator->total(),
            'lists'     => $lists,
        ];
    }

    /**
     * 截图、视频资源库详情
     * @param int $shopId
     * @param int $id
     * @return array
     */
    public function getResources(int $shopId, int $id): array
    {
        return ResourcesModel::query()
            ->where('id', $id)
            ->where('module', ResourcesModel::MODULE_TYPE_TOUR)
            ->where('business', ResourcesModel::BUSINESS_OPEN_TOUR)
            ->where('businessId', $shopId)
            ->get()
            ->map(
                function ($resourcesModel) {
                    $extra = json_decode($resourcesModel->extra, true);
                    return [
                        'id'        => $resourcesModel->id,
                        'url'       => picturePath($resourcesModel->url),
                        'type'      => $extra['type'] ?? "",
                        'name'      => $extra['name'] ?? "",
                        'thumbnail' => $extra['thumbnail'] ?? "",
                    ];
                }
            )->toArray();

    }

    /**
     * 删除
     * @param int $shopId
     * @param int $id
     * @param int $userId
     */
    public function delResources(int $shopId, int $id, int $userId)
    {
        ResourcesModel::query()
            ->where('id', $id)
            ->where('module', ResourcesModel::MODULE_TYPE_TOUR)
            ->where('business', ResourcesModel::BUSINESS_OPEN_TOUR)
            ->where('businessId', $shopId)
            ->update(['isDeleted' => 1, 'updatedByUid' => $userId]);
    }

    /**
     * 根据云巡店-稽核日期查询对应门店id
     * @param int $startTime
     * @param int $endTime
     * @return array
     */
    public static function getShopIdsByTourCruise(int $startTime, int $endTime): array
    {
        $shopIds = [];
        CruiseCheckDetailModel::query()
            ->with(['cruiseOrderRel'])
            ->where('templateType', CruiseTemplateModel::TYPE_6)
            ->whereBetween('submitTime', [$startTime, $endTime])
            ->chunkById(
                100, function ($item) use (&$shopIds) {
                foreach ($item as $v) {
                    $shopIds[] = $v->cruiseOrderRel->shopId ?? 0;
                }
            }
            );

        return array_unique($shopIds);
    }
}
